#include "Utils.h"
#include <cstring>

#include "api/GameInfo.h"

/*
void Linia(punkt p1, punkt p2)
{
    int x, xi1, xi2;
    int y, yi1, yi2;
    int dx, dy;
    int d, di1,di2;
    int numpix;

    dx = abs((int)(p2.x - p1.x));
    dy = abs((int)(p2.y - p1.y));

	if (dx >= dy)
	{
		numpix = dx + 1;
		d = (dy << 1) - dx;
		di1 = dy << 1;
		di2 = (dy - dx) << 1;
		xi1 = 1;
		xi2 = 1;
		yi1 = 0;
		yi2 = 1;
	}
	else
	{
		numpix = dy + 1;
		d = (dx << 1) - dy;
		di1 = dx << 1;
		di2 = (dx - dy) << 1;
		xi1 = 0;
		xi2 = 1;
		yi1 = 1;
		yi2 = 1;
	}

	if (p1.x > p2.x)
	{
		xi1 = -xi1;
		xi2 = -xi2;
	}
	if (p1.y > p2.y)
	{
		yi1 = -yi1;
		yi2 = -yi2;
	}

	x = (int)p1.x;
	y = (int)p1.y;

    for (int i = 0; i <= numpix; i++)
    {
		glBegin(GL_POINTS);
			glVertex2f((GLfloat) x, (GLfloat) y);
        glEnd();
        if (d < 0)
		{
			d += di1;
			x += xi1;
			y += yi1;
		}
        else
		{
            d += di2;
			x += xi2;
			y += yi2;
		}
	}
}
*/


bool Utils::IsLOS(const LevelInfo* level, const Vector2& v0, const Vector2& v1, float max_height)
{
    // TODO should use int only
    float x0 = v0.x;
    float y0 = v0.y;
    float x1 = v1.x;
    float y1 = v1.y;

    bool steep = fabsf(y1 - y0) > fabsf(x1 - x0);

    if (steep)
    {
        swap(x0, y0);
        swap(x1, y1);
    }

    if (x0 > x1)
    {
        swap(x0, x1);
        swap(y0, y1);
    }

    int deltax = (int) (x1 - x0);
    int deltay = (int) fabsf(y1 - y0);

    float error = 0.f;
    float deltaerr = (float) deltay / (float) deltax;
    int y = (int) y0;

    int ystep = (y0 < y1) ? 1 : -1;

    for (int x = (int) x0; x < (int) x1; ++x)
    {
        // TODO one if in loop

        uint ind;
        if (steep)
        {
            ind = y + x * level->width;
            //img.set_pixel(y, x, 0, 0, 255);
        }
        else
        {
            ind = x + y * level->width;
            //img.set_pixel(x, y, 0, 0, 255);
        }
        if (level->blockHeights[ind] > max_height)
            return false;

        error = error + deltaerr;

        if (error > 0.5f)
        {
            y = y + ystep;
            error = error - 1.0f;
        }
    }

    return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
Vector2 Utils::Rotate(const Vector2& v, float angle)
{
    Vector2 res;
    float cs = cosf(angle);
    float sn = sinf(angle);

    res.x = v.x * cs - v.y * sn;
    res.y = v.x * sn + v.y * cs;

    return res;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
bool Utils::IsLOS(const Vector2& v0, const Vector2& v1, bitmap_image& img)
{
    // TODO should use int only
    float x0 = v0.x;
    float y0 = v0.y;
    float x1 = v1.x;
    float y1 = v1.y;

    bool steep = fabsf(y1 - y0) > fabsf(x1 - x0);

    if (steep)
    {
        swap(x0, y0);
        swap(x1, y1);
    }

    if (x0 > x1)
    {
        swap(x0, x1);
        swap(y0, y1);
    }

    int deltax = (int) (x1 - x0);
    int deltay = (int) fabsf(y1 - y0);

    float error = 0.f;
    float deltaerr = (float) deltay / (float) deltax;
    int y = (int) y0;

    int ystep = (y0 < y1) ? 1 : -1;

    for (int x = (int) x0; x < (int) x1; ++x)
    {
        // TODO one if in loop
        if (steep)
            img.set_pixel(y, x, 0, 0, 255);
        else
            img.set_pixel(x, y, 0, 0, 255);

        error = error + deltaerr;

        if (error > 0.5f)
        {
            y = y + ystep;
            error = error - 1.0f;
        }
    }
    return false;
}
*/


///////////////////////////////////////////////////////////////////////////////////////////////////
MapBuffer::MapBuffer(uint width, uint height, float* data)
    : m_Width(width), m_Height(height)
{
    m_Data = new float[width * height];
    memcpy(m_Data, data, width * height * sizeof(float));
    //Clear();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void MapBuffer::Set(uint x, uint y, float value)
{
    assert(x < m_Width);
    assert(y < m_Height);

    m_Data[x + y * m_Width] = value;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void MapBuffer::Clear(float* data)
{
    for (uint i = 0; i < m_Width * m_Height; i++)
        m_Data[i] = 0.f;

    memcpy(m_Data, data, m_Width * m_Height * sizeof(float));
}